package com.forestar.mapControl.utils.mapConvert.geometry.coordinatesystem;

import android.util.SparseArray;

import com.forestar.mapControl.utils.mapConvert.geometry.Envelope;
import com.forestar.mapControl.utils.mapConvert.geometry.GeoPoint;
import com.forestar.mapControl.utils.mapConvert.geometry.IGeometry;

import java.util.HashMap;
import java.util.Map;

import static com.forestar.mapControl.utils.tile.TileConstants.*;


public class CoordinateSystem
  {
    public static final float DEG2RAD = (float) (Math.PI / 180.0);
    public static final float RAD2DEG = (float) (180.0 / Math.PI);
    public static final int RADIUS_EARTH_METERS = 6378137;

    private static final int SRID_BJ54 = 4214;
    private static final int SRID_XIAN80 = 4610;
    private static final int SRID_WGS84 = 4326;
    private static final int SRID_MERCATOR = 900913;
    private static final int SRID_CGCS2000 = 4490;
    private static boolean isAllGeoCoordTransParamsEnabled = true;
    private String name;
    private int srid;
    private CoordinateUnit coordUnit;
    private static SparseArray<CoordinateSystem> coordSystemMap = new SparseArray<>();
    private static CoordinateSystem WGS84LngLat = CoordinateSystem.createWGS84();

    private static Map<String, GeoTransformer> mapTransformers = new HashMap<String, GeoTransformer>();

    private CoordinateSystem(int srid)
      {
        this.srid = srid;
        // TODO 这里需要分析坐标单位，度，米，还有墨卡托的不能用于测量的单位
      }

    private static String getTransformerKey(CoordinateSystem from, CoordinateSystem to)
      {
        return String.valueOf(from.getSrid()) + "->" + String.valueOf(to.getSrid());
      }

    // 可强制设定所有的坐标转换是否使用设置的GNSS转换参数，用于简单偏移校正场景，不使用五参数、七参数、四参数等
    public static void setAllGeoCoordTransParamsEnable(boolean enabled)
      {
        isAllGeoCoordTransParamsEnabled = enabled;
      }

    public static GeoTransformer getTransformer(CoordinateSystem from, CoordinateSystem to)
      {
        String key = getTransformerKey(from, to);
        if (mapTransformers.containsKey(key))
          {
            return mapTransformers.get(key);
          }
        double[] params = getBaseSphereTransPrarameters(from, to);
        // 使用基准椭球的参数
        registTransformer(from, to, EllipsoidTransParamType.EllipsoidTransNull, params);
        GeoTransformer transformer = mapTransformers.get(key);
        // 当强制设置转换参数不可用时
        transformer.setUseParameters(isAllGeoCoordTransParamsEnabled);
        return transformer;
      }

    private static double[] getBaseSphereTransPrarameters(CoordinateSystem from, CoordinateSystem to)
      {
        // 找到基椭球参数
        CoordinateSystem fromBase = from;
        CoordinateSystem toBase = to;
        if (from.isProjectCoordinateSystem())
          {
            fromBase = from.getGeographicCoordinateSystem();
          }
        if (to.isProjectCoordinateSystem())
          {
            toBase = to.getGeographicCoordinateSystem();
          }
        double[] params = null;
        String keyBase = getTransformerKey(fromBase, toBase);
        if (mapTransformers.containsKey(keyBase))
          {
            GeoTransformer baseTrans = mapTransformers.get(keyBase);
            params = baseTrans.getParams();
          }
        return params;
      }

    public static boolean registTransformer(CoordinateSystem from, CoordinateSystem to, EllipsoidTransParamType transParamType, double[] parameters)
      {
        String key = getTransformerKey(from, to);
        GeoTransformer trans = new GeoTransformer(from, to, transParamType, parameters);
        mapTransformers.put(key, trans);
        projectCoordTransCopyParamFromGeoSR2GeoSR(from, to, parameters, key);
        String reversekey = getTransformerKey(to, from);
        double[] reverseParamters = new double[7];
        if (parameters != null)
          {
            for (int i = 0; i < parameters.length; i++)
              {
                reverseParamters[i] = -parameters[i];
              }
          }
        GeoTransformer to2FromTrans = new GeoTransformer(to, from, transParamType, reverseParamters);
        mapTransformers.put(reversekey, to2FromTrans);
        projectCoordTransCopyParamFromGeoSR2GeoSR(to, from, reverseParamters, reversekey);
        return true;
      }

    private static void projectCoordTransCopyParamFromGeoSR2GeoSR(CoordinateSystem from, CoordinateSystem to, double[] parameters, String key)
      {
        // 如果都是地理的坐标系统，且设置的参数不为空，要做一次更新
        if (from.isGeographicCoordinateSystem() && to.isGeographicCoordinateSystem() && parameters != null)
          {
            for (String itemKey : mapTransformers.keySet())
              {
                String[] srids = itemKey.split("->");
                CoordinateSystem cs1 = CoordinateSystem.create(Integer.parseInt(srids[0]));
                CoordinateSystem cs2 = CoordinateSystem.create(Integer.parseInt(srids[1]));
                // 如果是衍生坐标系，需要使用基准椭球的来更新
                if (cs1.isProjectCoordinateSystem() || cs2.isProjectCoordinateSystem())
                  {
                    CoordinateSystem cs1geo = cs1.getGeographicCoordinateSystem();
                    CoordinateSystem cs2geo = cs2.getGeographicCoordinateSystem();
                    String baseKey = getTransformerKey(cs1geo, cs2geo);
                    if (baseKey.compareToIgnoreCase(key) == 0)
                      {
                        mapTransformers.get(itemKey).setParameters(mapTransformers.get(key).getParams());
                      }
                  }
              }
          }
      }

    public static double pointDistanceToPoint(double lon1, double lat1, double lon2, double lat2)
      {
        final double a1 = DEG2RAD * lat1;
        final double a2 = DEG2RAD * lon1;
        final double b1 = DEG2RAD * lat2;
        final double b2 = DEG2RAD * lon2;
        final double cosa1 = Math.cos(a1);
        final double cosb1 = Math.cos(b1);
        final double t1 = cosa1 * Math.cos(a2) * cosb1 * Math.cos(b2);
        final double t2 = cosa1 * Math.sin(a2) * cosb1 * Math.sin(b2);
        final double t3 = Math.sin(a1) * Math.sin(b1);
        final double tt = Math.acos(t1 + t2 + t3);
        return (int) (RADIUS_EARTH_METERS * tt);
      }

    public static CoordinateSystem createMercator()
      {
        return create(SRID_MERCATOR);
      }

    /**
     * 是否是地理坐标系统
     *
     * @return
     */
    public boolean isGeographicCoordinateSystem()
      {
        return srid == SRID_BJ54 || srid == SRID_WGS84 || srid == SRID_XIAN80 || srid == SRID_CGCS2000;
      }

    /**
     * 是否是投影（平面）坐标系统
     *
     * @return
     */
    public boolean isProjectCoordinateSystem()
      {
        if (srid == 4326)
          {
            return false;
          } else if (srid == 4214)
          {
            //"北京1954坐标系 经纬度";
            return false;
          } else if (srid == 4610)
          {
            //""西安1980坐标系 经纬度";
            return false;
          } else if (srid == 4490)
          {
            //""国家2000坐标系 经纬度";
            return false;
          }
        return true;
      }

    /**
     * 根据SRID创建坐标系统对象，一次创建，重复使用
     *
     * @param srid
     * @return
     */
    public static CoordinateSystem create(int srid)
      {
        CoordinateSystem coordinateSystem = coordSystemMap.get(srid);
        if (coordinateSystem != null)
          {
            return coordinateSystem;
          }
        CoordinateSystem cs = new CoordinateSystem(srid);
        coordSystemMap.put(srid, cs);
        return cs;
      }

    public static CoordinateSystem createBeijing1954()
      {
        return new CoordinateSystem(4214);
      }

    public static CoordinateSystem createProjectBeijing1954(ZoneType zoneType, int zoneNumber, boolean withZoonCode)
      {
        int sridBegin = 2400;
        int startOffset = 24;
        switch (zoneType)
          {
            case ZoneType3:
              sridBegin = withZoonCode ? 2400 : 2421;
              startOffset = 24;
              break;
            case ZoneType6:
              sridBegin = withZoonCode ? 21412 : 21452;
              startOffset = 12;
              break;
            default:
          }
        return create(sridBegin + zoneNumber - startOffset);
      }

    public static CoordinateSystem createXian1980()
      {
        return new CoordinateSystem(4610);
      }

    public static CoordinateSystem createProjectXian1980(ZoneType zoneType, int zoneNumber, boolean withZoonCode)
      {
        int sridBegin = 2348;
        int startOffset = 24;
        switch (zoneType)
          {
            case ZoneType3:
              sridBegin = withZoonCode ? 2348 : 2369;
              startOffset = 24;
              break;
            case ZoneType6:
              sridBegin = withZoonCode ? 2326 : 2337;
              startOffset = 12;
              break;
            default:
          }
        return create(sridBegin + zoneNumber - startOffset);
      }

    public static CoordinateSystem createWGS84()
      {
        return new CoordinateSystem(4326);
      }

    public static CoordinateSystem createProjectWGS84(ZoneType zoneType, int zoneNumber, boolean withZoonCode)
      {
        int sridBegin = 1000022;
        int startOffset = 24;
        switch (zoneType)
          {
            case ZoneType3:
              sridBegin = withZoonCode ? 1000022 : 1000043;
              startOffset = 24;
              break;
            case ZoneType6:
              sridBegin = withZoonCode ? 1000000 : 1000011;
              startOffset = 12;
              break;
            default:
          }
        return create(sridBegin + zoneNumber - startOffset);
      }

    public static CoordinateSystem createCGCS2000()
      {
        return new CoordinateSystem(4490);
      }

    public static CoordinateSystem createProjectCGCS2000(ZoneType zoneType, int zoneNumber, boolean withZoonCode)
      {
        int sridBegin = 4512;
        int startOffset = 24;
        switch (zoneType)
          {
            case ZoneType3:
              sridBegin = withZoonCode ? 4512 : 4533;
              startOffset = 24;
              break;
            case ZoneType6:
              sridBegin = withZoonCode ? 4490 : 4501;
              startOffset = 12;
              break;
            default:
          }
        return create(sridBegin + zoneNumber - startOffset);
      }

    public boolean equals(Object other)
      {
        if (this == other)
          return true;
        if (other == null)
          return false;
        if (!(other instanceof CoordinateSystem))
          return false;
        final CoordinateSystem cat = (CoordinateSystem) other;
        if (getSrid() != cat.getSrid())
          return false;
        return true;
      }

    public int getSrid()
      {
        return srid;
      }

    public static void projectPoint(CoordinateSystem from, CoordinateSystem to, double[] point)
      {
        if (from.srid == to.srid)
          {
            return;
          }
        GeoTransformer transformer = CoordinateSystem.getTransformer(from, to);
        transformer.transform(point);
      }

    public static void projectPoint(GeoPoint point, GeoPoint outPoint)
      {
        CoordinateSystem from = point.getCoordinateSystem();
        CoordinateSystem to = outPoint.getCoordinateSystem();
        if (from != to)
          {
            double[] coord = new double[]{point.getX(), point.getY()};
            projectPoint(from, to, coord);
            outPoint.setX(coord[0]);
            outPoint.setY(coord[1]);
          } else
          {
            //outPoint = point;
            outPoint.setX(point.getX());
            outPoint.setY(point.getY());
          }
      }

    public static void lonLat2Mercator(double[][] lngLats)
      {
        for (int i = 0; i < lngLats.length; i++)
          {
            lngLats[i][0] = lngLats[i][0] * 20037508.3427892 / 180;
            lngLats[i][1] = Math.log(Math.tan((90 + lngLats[i][1]) * 3.14159265358979323846 / 360)) / (3.14159265358979323846 / 180);
            lngLats[i][1] *= 20037508.347892 / 180;
          }
      }

    public static void Mercator2lonLat(double[][] lngLats)
      {
        for (int i = 0; i < lngLats.length; i++)
          {
            lngLats[i][0] = lngLats[i][0] / 20037508.347892 * 180;
            lngLats[i][1] = lngLats[i][1] / 20037508.347892 * 180;
            lngLats[i][1] = 180 / 3.14159265358979323846 * (2 * Math.atan(Math.exp(lngLats[i][1] * 3.14159265358979323846 / 180)) - 3.14159265358979323846 / 2);
          }
      }

    public static void lonLat2Mercator(double lon, double lat, double[] outxy)
      {
        lon = lon * 20037508.347892 / 180;
        lat = Math.log(Math.tan((90 + lat) * 3.14159265358979323846 / 360)) / (3.14159265358979323846 / 180);
        lat *= 20037508.347892 / 180;
        outxy[0] = lon;
        outxy[1] = lat;
      }

    public static void Mercator2lonLat(double lon, double lat, double[] outxy)
      {
        lon = lon / 20037508.347892 * 180;
        lat = lat / 20037508.347892 * 180;
        lat = 180 / 3.14159265358979323846 * (2 * Math.atan(Math.exp(lat * 3.14159265358979323846 / 180)) - 3.14159265358979323846 / 2);
        outxy[0] = lon;
        outxy[1] = lat;
      }

    // 底层转换
    public static void projectPointsArray(double[] xy, int numPoints)
      {
      }

    public boolean equalsEllipsoid(CoordinateSystem to)
      {
        return false;
      }

    public boolean baseOnXian80()
      {
        return false;
      }

    public boolean baseOnBeijing54()
      {
        return false;
      }

    public boolean baseOnWGS84()
      {
        return srid == SRID_WGS84;
      }

    public boolean baseOnCGCS2000()
      {
        return srid == SRID_CGCS2000;
      }

    public boolean isWebMercator()
      {
        return srid == SRID_MERCATOR;
      }

    public CoordinateSystem getGeographicCoordinateSystem()
      {
        // TODO 这里必须要求算其真实地理坐标系统 这里只是为测试用 liubo 2016年8月8日15:11:21
        CoordinateSystem geographicCoordinateSystem = null;
        if (this.srid == SRID_MERCATOR)
          {
            return CoordinateSystem.createWGS84();
          }
        String strCoorDes = "";
        if (srid == 3395 || srid == 900913 || srid == 3857 || srid == 102100 || srid == 102113 || srid == 54004)
          {
            strCoorDes = "世界墨卡托投影坐标系";
            return CoordinateSystem.createWGS84();
          } else if (srid == 4326)
          {
            strCoorDes = "WGS84坐标系 经纬度";
            return this;
          } else if (srid == 4214)
          {
            strCoorDes = "北京1954坐标系 经纬度";
            return this;
          } else if (srid == 4610)
          {
            strCoorDes = "西安1980坐标系 经纬度";
            return this;
          } else if (srid == 4490)
          {
            strCoorDes = "国家2000坐标系 经纬度";
            return this;
          } else if (srid > 2400 && srid < 2422)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2400 + 24) + "带(加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 2421 && srid < 2443)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2421 + 24) + "带(不加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 21412 && srid < 21424)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21412 + 12) + "带(加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 21452 && srid < 21464)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21452 + 12) + "带(不加带号)";
            return CoordinateSystem.createBeijing1954();
          } else if (srid > 2348 && srid < 2370)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2348 + 24) + "带(加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2369 && srid < 2391)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2369 + 24) + "带(不加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2326 && srid < 2338)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2326 + 12) + "带(加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 2337 && srid < 2349)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2337 + 12) + "带(不加带号)";
            return CoordinateSystem.createXian1980();
          } else if (srid > 4512 && srid < 4534)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4512 + 24) + "带(加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4533 && srid < 4555)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4533 + 24) + "带(不加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4490 && srid < 4502)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4490 + 12) + "带(加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 4501 && srid < 4513)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4501 + 12) + "带(不加带号)";
            return CoordinateSystem.createCGCS2000();
          } else if (srid > 1000022 && srid < 1000044)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000022 + 24) + "带(加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000043 && srid < 1000065)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000043 + 24) + "带(不加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000000 && srid < 1000012)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000000 + 12) + "带(加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid > 1000011 && srid < 1000023)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000011 + 12) + "带(不加带号)";
            return CoordinateSystem.createWGS84();
          } else if (srid == 1000000)
          {
            strCoorDes = "北京地方坐标系";
            return CoordinateSystem.createBeijing1954();
          } else
          {
            strCoorDes = "未知坐标系统";
          }
        // TODO liubo 2017年6月11日19:22:34  找不到坐标系，必须报异常
        return null;
      }

    public static String getCoordinateSystemName(int srid)
      {
        // TODO 这里必须要求算其真实地理坐标系统 这里只是为测试用 liubo 2016年8月8日15:11:21
        String strCoorDes = null;
        if (srid == 3395 || srid == 900913 || srid == 3857 || srid == 102100 || srid == 102113 || srid == 54004)
          {
            strCoorDes = "世界墨卡托投影坐标系";
          } else if (srid == 4326)
          {
            strCoorDes = "WGS84坐标系 经纬度";
          } else if (srid == 4214)
          {
            strCoorDes = "北京1954坐标系 经纬度";
          } else if (srid == 4610)
          {
            strCoorDes = "西安1980坐标系 经纬度";
          } else if (srid == 4490)
          {
            strCoorDes = "国家2000坐标系 经纬度";
          } else if (srid > 2400 && srid < 2422)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2400 + 24) + "带(加带号)";
          } else if (srid > 2421 && srid < 2443)
          {
            strCoorDes = "北京54坐标系3度分带" + String.valueOf(srid - 2421 + 24) + "带(不加带号)";
          } else if (srid > 21412 && srid < 21424)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21412 + 12) + "带(加带号)";
          } else if (srid > 21452 && srid < 21464)
          {
            strCoorDes = "北京54坐标系6度分带" + String.valueOf(srid - 21452 + 12) + "带(不加带号)";
          } else if (srid > 2348 && srid < 2370)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2348 + 24) + "带(加带号)";
          } else if (srid > 2369 && srid < 2391)
          {
            strCoorDes = "西安80坐标系3度分带" + String.valueOf(srid - 2369 + 24) + "带(不加带号)";
          } else if (srid > 2326 && srid < 2338)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2326 + 12) + "带(加带号)";
          } else if (srid > 2337 && srid < 2349)
          {
            strCoorDes = "西安80坐标系6度分带" + String.valueOf(srid - 2337 + 12) + "带(不加带号)";
          } else if (srid > 4512 && srid < 4534)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4512 + 24) + "带(加带号)";
          } else if (srid > 4533 && srid < 4555)
          {
            strCoorDes = "国家2000坐标系3度分带" + String.valueOf(srid - 4533 + 24) + "带(不加带号)";
          } else if (srid > 4490 && srid < 4502)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4490 + 12) + "带(加带号)";
          } else if (srid > 4501 && srid < 4513)
          {
            strCoorDes = "国家2000坐标系6度分带" + String.valueOf(srid - 4501 + 12) + "带(不加带号)";
          } else if (srid > 1000022 && srid < 1000044)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000022 + 24) + "带(加带号)";
          } else if (srid > 1000043 && srid < 1000065)
          {
            strCoorDes = "WGS84高斯投影坐标系3度分带" + (srid - 1000043 + 24) + "带(不加带号)";
          } else if (srid > 1000000 && srid < 1000012)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000000 + 12) + "带(加带号)";
          } else if (srid > 1000011 && srid < 1000023)
          {
            strCoorDes = "WGS84高斯投影坐标系6度分带" + (srid - 1000011 + 12) + "带(不加带号)";
          } else if (srid == 1000000)
          {
            strCoorDes = "北京地方坐标系";
          }
        // TODO liubo 2017年6月11日19:22:34  找不到坐标系，必须报异常
        return strCoorDes;
      }

    public static ZoneType getCoordinateSystemZoneType(int srid)
      {
        ZoneType zoneType = ZoneType.ZoneTypeUnKnow;
        if (srid == 3395 || srid == 900913 || srid == 3857 || srid == 102100 || srid == 102113 || srid == 54004 || srid == 4490 || srid == 4610 || srid == 4326 || srid == 4214)
          {
            zoneType = ZoneType.ZoneTypeUnKnow;
          } else if (srid > 2400 && srid < 2422)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 2421 && srid < 2443)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 21412 && srid < 21424)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 21452 && srid < 21464)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 2348 && srid < 2370)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 2369 && srid < 2391)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 2326 && srid < 2338)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 2337 && srid < 2349)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 4512 && srid < 4534)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 4533 && srid < 4555)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 4490 && srid < 4502)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 4501 && srid < 4513)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 1000022 && srid < 1000044)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 1000043 && srid < 1000065)
          {
            zoneType = ZoneType.ZoneType3;
          } else if (srid > 1000000 && srid < 1000012)
          {
            zoneType = ZoneType.ZoneType6;
          } else if (srid > 1000011 && srid < 1000023)
          {
            zoneType = ZoneType.ZoneType6;
          }
        return zoneType;
      }

    // TODO 面积计算方法，需要补充
    public static double calculateArea(IGeometry geometry)
      {
        return 0;
      }

    public static Envelope transform(CoordinateSystem coordSystemFrom, CoordinateSystem coordSystemTo, Envelope envelope)
      {
        GeoPoint leftUpper = new GeoPoint(coordSystemFrom, envelope.getXMin(), envelope.getYMax());
        GeoPoint lowerRight = new GeoPoint(coordSystemFrom, envelope.getXMax(), envelope.getYMin());
        GeoPoint leftUpperOut = new GeoPoint(coordSystemTo, 0, 0);
        GeoPoint lowerRightOut = new GeoPoint(coordSystemTo, 0, 0);
        CoordinateSystem.projectPoint(leftUpper, leftUpperOut);
        CoordinateSystem.projectPoint(lowerRight, lowerRightOut);
        Envelope env = new Envelope(coordSystemTo, leftUpperOut.getX(), lowerRightOut.getX(), lowerRightOut.getY(), leftUpperOut.getY());
        return env;
      }

    /**
     * 获得对应平面坐标系
     *
     * @param from
     * @param dx
     * @param zoneType
     * @param withZoonCode
     * @return
     */
    public static CoordinateSystem getPlaneCoordinaSystem(CoordinateSystem from, double dx, ZoneType zoneType, boolean withZoonCode)
      {
        int zoneNumber = zoneType == ZoneType.ZoneType3 ? ((int) (dx - 1.5) / 3) + 1 : ((int) dx / 6) + 1;
        CoordinateSystem out = from;
        switch (from.getSrid())
          {
            case 4214:
              out = CoordinateSystem.createProjectBeijing1954(zoneType, zoneNumber, withZoonCode);
              break;
            case 4610:
              out = CoordinateSystem.createProjectXian1980(zoneType, zoneNumber, withZoonCode);
              break;
            case 4490:
              out = CoordinateSystem.createProjectCGCS2000(zoneType, zoneNumber, withZoonCode);
              break;
            case 4326:
              out = CoordinateSystem.createProjectWGS84(zoneType, zoneNumber, withZoonCode);
            default:
          }
        return out;
      }

    public double getXMin()
      {
        if (this.isWebMercator())
          {
            return MERCATOR_XMIN;
          }
        return -999999999;
      }

    public double getXMax()
      {
        if (this.isWebMercator())
          {
            return MERCATOR_XMAX;
          }
        return 999999999;

      }

    public double getYMin()
      {
        if (this.isWebMercator())
          {
            return MERCATOR_YMIN;
          }
        return -999999999;
      }

    public double getYMax()
      {
        if (this.isWebMercator())
          {
            return MERCATOR_YMAX;
          }
        return 999999999;
      }

    public String getName()
      {
        return CoordinateSystemHelper.GetCoordDescription(srid);
      }

    public void limitExtent(Envelope envelope)
      {
        double xMin = envelope.getXMin();
        double xMax = envelope.getXMax();
        double yMin = envelope.getYMin();
        double yMax = envelope.getYMax();
        // 如果是地理坐标系统，范围要强制约束
        if (this.isGeographicCoordinateSystem())
          {
            xMin = (xMin < -180 || xMin > 180) ? -180 : xMin;
            xMax = (xMax < -180 || xMax > 180) ? 180 : xMax;
            yMin = (yMin < -90 || yMin > 90) ? -90 : yMin;
            yMax = (yMax < -90 || yMax > 90) ? 90 : yMax;
            envelope.setXMin(xMin);
            envelope.setXMax(xMax);
            envelope.setYMin(yMin);
            envelope.setYMax(yMax);
          } else if (this.isWebMercator())
          {
            xMin = (xMin < MERCATOR_XMIN || xMin > MERCATOR_XMAX) ? MERCATOR_XMIN : xMin;
            xMax = (xMax < MERCATOR_XMIN || xMax > MERCATOR_XMAX) ? MERCATOR_XMAX : xMax;
            yMin = (yMin < MERCATOR_YMIN || yMin > MERCATOR_YMAX) ? MERCATOR_YMIN : yMin;
            yMax = (yMax < MERCATOR_YMIN || yMax > MERCATOR_YMAX) ? MERCATOR_YMAX : yMax;
            envelope.setXMin(xMin);
            envelope.setXMax(xMax);
            envelope.setYMin(yMin);
            envelope.setYMax(yMax);

          }

      }
  }
